#include <stdlib.h>
#include <string.h>
#include <assert.h>

#include "utils.h"
#include "cobject.h"

/*==========================================================================
*宏、枚举、类型、结构体、全局变量、函数声明
*==========================================================================*/

#define FLAG_BYTE0 0xAA
#define FLAG_BYTE1 0xBB
#define FLAG_BYTE2 0xCC
#define FLAG_BYTE3 0xDD

/*===============================================================================
*私有函数
*===============================================================================*/

// 是否为类对象
static int __is_cobject(cclass *cls)
{
#if 0
    debug("flag:%02X%02X%02X%02X name:%s size:%d\n",
        cls->flag[0], cls->flag[1], cls->flag[2], cls->flag[3],
        cls->info.name, cls->info.size);
#endif

    return (cls->flag[0] == FLAG_BYTE0 &&
            cls->flag[1] == FLAG_BYTE1 &&
            cls->flag[2] == FLAG_BYTE2 &&
            cls->flag[3] == FLAG_BYTE3 &&
            cls->info.name &&
            cls->info.size > 0);
}

/*===============================================================================
* 接口函数
*===============================================================================*/

cobject cobject_new(char *cclass_name, int cclass_size)
{
    cobject obj = COBJECT_NONE;

    assert(cclass_name);
    assert(cclass_size);

    obj = calloc(1, cclass_size);
    if (obj) cobject_ctor(obj, cclass_name, cclass_size);
    return obj;
}

void cobject_del(cobject obj)
{
    assert(obj);
    assert(__is_cobject(obj));

    cobject_dtor(obj);
    free(obj);
}

void cobject_ctor(cobject obj, char *cclass_name, int cclass_size)
{
    cclass *cls = obj;

    assert(obj);
    assert(cclass_name);
    assert(cclass_size);

    cls->flag[0] = FLAG_BYTE0;
    cls->flag[1] = FLAG_BYTE1;
    cls->flag[2] = FLAG_BYTE2;
    cls->flag[3] = FLAG_BYTE3;

    cls->info.name = cclass_name;
    cls->info.size = cclass_size;
    cls->inherit = NULL;
    cls->inherit_nr = 0;
}

void cobject_dtor(cobject obj)
{
    cclass *cls = obj;

    assert(obj);
    assert(__is_cobject(obj));

    free(cls->inherit);

    cls->flag[0] = 0x00;
    cls->flag[1] = 0x00;
    cls->flag[2] = 0x00;
    cls->flag[3] = 0x00;
    cls->info.name = NULL;
    cls->info.size = 0;
    cls->inherit = NULL;
    cls->inherit_nr = 0;
}

void cobject_inherit(cobject obj, cobject parent)
{
    cclass *cls = obj;

    assert(obj);
    assert(parent);
    assert(__is_cobject(obj));
    assert(__is_cobject(parent));

    cls->inherit = cls->inherit_nr == 0 ?
                   calloc(1, sizeof(cobject)) :
                   realloc(cls->inherit, cls->inherit_nr + 1);
    if (cls->inherit) {
        cls->inherit[cls->inherit_nr] = parent;
        cls->inherit_nr++;
    }
}

cclass_info cobject_id(cobject obj)
{
    cclass_info info = CCLASS_INFO_NONE;
    cclass *cls = obj;

    assert(obj);
    assert(__is_cobject(obj));

    if (__is_cobject(cls)) info = cls->info;
    return info;
}

int cobject_type(cobject obj, char *cclass_name)
{
    cclass *cls = obj;

    assert(obj);
    assert(cclass_name);

    return (__is_cobject(cls) && !strcmp(cclass_name, cls->info.name));
}

cobject cobject_self(cobject obj, char *cclass_name)
{
    int i;
    cclass *cls = obj;
    cobject self = COBJECT_NONE;

    assert(obj);
    assert(cclass_name);
    assert(__is_cobject(obj));

    do {
        // 本类对象
        if (cobject_type(obj, cclass_name)) {
            self = obj;
            break;
        }

        // 无父类对象
        if (cls->inherit_nr == 0) break;

        // 查找父类对象
        for (i = 0; i < cls->inherit_nr; i++) {
            self = cobject_self(cls->inherit[i], cclass_name);
            if (self) break;
        }
    } while (0);

    return self;
}